<?php

namespace Sharks\Core\Persistence\QueryBuilder;
use Sharks\Core\Support\Base\Str;

/**
 * 表达式方法合集
 */
abstract class AbstractExpressionQuery extends AbstractSelectQuery {

    /**
     * SQL 'is null'
     * @param $column
     * @return $this
     */
    public function isNull($column) {
        $e = $this->getQuery()->expr->isNull($column);
        $this->getQuery()->where($e);
        return $this;
    }

    /**
     * SQL =
     * @param $column
     * @param $value
     * @return $this|SelectQuery
     */
    public function eq($column, $value) {
        return $this->where($column, $value);
    }

    /**
     * SQL <> or !=
     * @param $column
     * @param $value
     * @return $this|SelectQuery
     */
    public function neq($column, $value) {
        return $this->where($column, $value, 'neq');
    }

    /**
     * SQL is not null
     * @param $column
     * @return $this
     */
    public function not($column) {
        $e = $this->getQuery()->expr;
        $e->eq($column, $e->not('null'));
        $this->getQuery()->where($e);
        return $this;
    }

    /**
     * SQL $value1 > $value2
     * @param $value1
     * @param $value2
     * @return $this|SelectQuery
     */
    public function gt($value1, $value2) {
        return $this->where($value1, $value2, 'gt');
    }

    /**
     * SQL $value1 >= $value2
     * @param $value1
     * @param $value2
     * @return $this|SelectQuery
     */
    public function gte($value1, $value2) {
        return $this->where($value1, $value2, 'gte');
    }

    /**
     * SQL $value1 < $value2
     * @param $value1
     * @param $value2
     */
    public function lt($value1, $value2) {
        return $this->where($value1, $value2, 'lt');
    }

    /**
     * SQL $value1 <= $value2
     * @param $value1
     * @param $value2
     * @return $this|SelectQuery
     */
    public function lte($value1, $value2) {
        return $this->where($value1, $value2, 'lte');
    }

    /**
     * SQL in
     * @param $column
     */
    public function in($column) {
        $args = func_get_args();
        forward_static_call_array(array($this->getQuery(), 'in'), $args);
        return $this;
    }

    public function where($column, $value, $operator = 'eq') {
        $e = $this->getQuery()->expr->$operator($column, $this->getQuery()->bindValue($value));
        $this->getQuery()->where($e);
        return $this;
    }

    /**
     * 便捷方法
     * (1) ->byXXX($value) 等同于 ->eq('XXX', $value);
     * (2) ->likeByXXX($value) 等同于 ->like('XXX', $value);
     * @param $name
     * @param $args
     */
    public function __call($name, $args) {

        if (Str::startsWith($name, 'by')) {
            $column = lcfirst(substr($name, 2));
            $this->eq($column, $args[0]);
        }
        elseif (Str::startsWith($name, 'likeBy')) {
            $column = lcfirst(substr($name, 6));
            $this->like($column, $args[0]);
        }
        return $this;
    }

    /**
     * 获得SQL
     * @return string
     */
    public function toSql() {
        return $this->getQuery()->getQuery();
    }

    public function getParams() {
        return $this->getQuery();
    }

    protected abstract function getQuery();

}